こだわり
2004-08-26 01:29:23 ( ID:1dmvss/ucbw )
[ 削除 / 引用して返信 ]
MPEG1 Audio のエンコード・デコードで発生する遅延と、TMPGEncでMPEG1 Audioを
扱う際に発生する「音ズレ」について、少々長くなりますが書かせてください。
「音ズレ」が非常にデリケートな話題であることは検索してわかっているつもり
ですが、ひとまず全て忘れて読んでいただきたいです。
最近、MP3というものはエンコード・デコードによって必ず先頭に一定の無音区間を
発生することを発見し、ならばLayer-1,2 でもそうなのかと、実験してみたのです。
開発者さんは当然知っている事だと思いますが、知らない人も多いでしょうし、
まずはその実験結果を晒してみます。
(実験方法は、後で紹介する資料によってウラが取れたので割愛します)
Layer-1 (TMPEG Enc Free Ver.2.521.58.169)
delay = 545 samples
0.017031 sec at 32000Hz
0.012358 sec at 44100Hz
0.011354 sec at 48000Hz
Layer-2 (TMPEG Enc Free Ver.2.521.58.169)
delay = 481 samples (241 by encoder + 240 by decoder)
0.015031 sec at 32000Hz
0.010907 sec at 44100Hz
0.010021 sec at 48000Hz
Layer-3 (午後のこ〜だ wingogo.exe Ver.3.11a CBR)
delay = 1105 samples (576 by encoder + 529 by decoder)
0.034531 sec at 32000Hz
0.025057 sec at 44100Hz
0.023021 sec at 48000Hz
samplesはいうまでもなく波形を数値化している回数です。それだけ先頭に余分な
無音部分ができたということです。
この結果から言えることは、
「もし、1ms たりとも音ズレを容認できないというなら、MPEG1 Layer-2 44.1kHz
でエンコする場合にはソースの範囲の設定で音ズレ補正を+11msにするべきだ」
ということです。これによってソースの先頭11msの音は失われてしまいますが、
音ズレは最小限に抑えらるわけです。
ちなみに数字が判明したので検索をかけたところ、裏づけとなる資料を発見。
Layer-2 に関しては http://www.aes.org/standards/b_pub/aes41-2000.pdf
これの最後のほう Annex B で解説されています。英語だし正直理屈までは
わかりませんが、これによって 481samplesのうち241はエンコーダによって、
240はデコーダによって発生する、ということが判明しました。
Layer-3 に関しては http://mp3decoders.mp3-tech.org/decoders_lame.html
に、各種エンコーダーで何サンプル遅れるかが書いてあります。
「午後のこ〜だ」はLAMEがベースですからLAMEと同じですね。
さて、私は酷くても1フレーム程度に納まる音ズレくらいでガタガタ言うものでは
ありません。見てもわからないですから。
しかしながら疑問は湧きます。「何サンプルなのか判っているのなら、なぜ
エンコーダ、デコーダそれぞれで余分に発生する部分のデータを捨てないのか?」
エンコードルーチンが吐き出したデータの先頭nサンプルを読み捨ててファイルに
書き出せば済むのでは? デコーダも同様にすればよいのでは?
不思議です。
http://bbs.pegasys-inc.com/bbscgi/search/docs/ja/te30/box04/te30_post_1524.html
の検証担当さんがおっしゃる事ももっともではありますが、エンコーダを内蔵する
TMPGEncならばエンコード時の遅延に関してTMPGEnc内で対処することが可能なはず。
デコード時の分までは責任は持てないとしても、TMPGEncはMPEG1の場合にはWindowsの
デコーダを使用しているのですから、読み込んだときにWindowsデコーダを前提とした
補正をしてくれてもよさそうなものです。何サンプル補正するかを設定できるようにすれば、
将来Windowsに変更があった時にも対応できるでしょうし。いかがでしょう?
更にもう一つ、エンコーダ・デコーダに関係ない部分でTMPGEnc自体が音ズレを作って
いるのではないかと思われる現象を確認しました。どうかもう少しお付き合いください。
長くなりすぎたのでここで区切ります。
こだわり
2004-08-26 01:31:56 ( ID:1dmvss/ucbw )
[ 削除 / 引用して返信 ]
一言で言うと、映像の長さと音声の長さが一致する事は非常に稀である、という事です。
上で書いた481サンプル増えるというのを差し引いてもです。
簡単にこの現象を確認するには、TMPGEncでエンコードしたファイルをTMPGEncに
読み込んで、「ソース範囲」の設定画面で音声ヒストグラムの線が端っこと一致して
いるか、音ズレ補正の値を+1(上記のズレがあるので実際には+12とか)したときに
線の終わりが見えるか、を確認することでわかります。
経験上、これがピタリと一致する事は稀で、大抵は音声が数ミリ〜数十ミリ秒長く、
1フレーム分より長い場合には最終フレームの映像が続く形で総フレーム数が増えます。
極々稀に音声が短い場合もあります。また、サンプリングレートが高いほどズレ幅が
小さい傾向があります。
私はこの現象を抑えるために、総フレーム数を増減させて何度もエンコして様子を
見たりします。1フレームの増減で何ミリ秒のズレが出るか変わってくるからです。
繰り返しますが、私は数フレーム程度の音ズレであれば、意志の力で無視できます。
しかしながら、音声が長くなったり最終フレームの画像が数フレーム続くことによって
困る場合というのもあります。それはMPEGを何個か連結した場合です。
スムースに繋がるべきところで同じ画像が数瞬続くとか、何個も連結したら
終いの方は1秒ちかく音がずれてる、てな事になると流石に気になってしまいます。
これについても実験を行いました。長くなるのでデータは割愛しますが、手順を大まかに
書いておきます。
・まずは「ソースがおかしいのでは? TMPGEncはTMPGEncでエンコしたもの以外…」などと
言われないソースの用意です。
TMPGEncで短めのWAVを音声ソースとして読み込みます。今回、Win2K に入っている
「ユートピア - ごみ箱を空にする.WAV」を使用しました。
映像ソースは読み込まずに、出力形式を通常の System(Video+Audio)で圧縮実行します。
できたファイルを読み込むと、映像は真っ黒で、MPEG-1 352*240 29.97fps CBR 1150kbps,
Layer-2 44100Hz 192kbps、総フレーム数66のMPEG1ファイルができたようです。
・「映像ソースを読み込まないので変なものができたのではないか?」と言われるかも
しれませんが、ちなみに分離してできた.m1vファイルを某プラグイン使用で読み込んで
みたところ、総フレーム65フレームのファイルであることを確認しました。
すでにこの時点で音声が長くなって1フレーム増えていることがわかりますが、
とりあえず無視です。
・これをソースとして、開始フレームを0、終了フレームを0〜9で変化させて、
10個のMPEG1ファイルを作成しました。また同時に「ファイルに出力」でWAVファイルも
作ってみました。
・10個のMPEGファイルそれぞれで、「ファイルに出力」で音声をWAVとして取り出します。
これで2種類のWAVが10個できます。一方は範囲の設定だけしてエンコードを通していない
音声データ、もう一方はエンコード後に取り出したデータです。
・それぞれのWAVファイルを「Audacity」(*)で読み込んで、エンコ前に設定した総フレーム数
からどれだけの余分なデータが存在するかを読み取ります。
(*)Audacity:
http://www.forest.impress.co.jp/lib/pic/music/soundedit/audacity.html
日本語表示ができる海外ソフトですが、ほとんど文字化けしているので英語で使用のこと
すみません、また区切ります。
こだわり
2004-08-26 01:32:57 ( ID:1dmvss/ucbw )
[ 削除 / 引用して返信 ]
以上で得られたデータを眺めてみると…何がどうなってこうなるのかさっぱり???
面白い(?)のはエンコ前とエンコ後の音声データを抜き出したわけですがこの二つの
長さ、内容が一致しないことです。エンコ前のものは単に長くなっているだけですが、
エンコ後のものは途中から無音になっている場合が多い。そして9〜10フレーム分も
長かったりする物もありました。
一例をあげると、総フレーム数5のものは、(上がエンコ前、下がエンコ後、先頭481サンプル含む)
フレーム数
A:期待されるサンプル数(秒換算)
B:生成されたWAV中のサンプル数(秒換算)
B-A:余分に生成されたサンプル数(秒換算: フレーム換算)
備考
05: 7357(.166825) 10367(.235079) 3010(.068254: 2.045)
05: 7357(.166825) 22287(.505374) 14930(.338549: 10.146) 0.1967秒付近から無音
これだと10フレームも増えていますが、普通に使っていて10フレームも増えることは
そうそうないですね。
ひとつ確かだと思える事は、エンコ前にWAVファイル出力しても音が長くなるということは
エンコードとかかわり無いところで何か間違った数値を吐き出すような計算が行われている、
という事です。TMPGEncのコーディング中のバグか、または誤差の大きい計算手順、
あるいはひょっとして何かWindowsに由来する不具合かもしれません。
いずれにしろ、圧縮伸張もしていないのに+-1サンプルより大きい誤差がでるのは
異常としか思えないのです。
検証担当さん、どうお考えになりますか? 取り敢えず、この問題を認識されておられるのか?
不可避のものなのか? そこのところが知りたいです。Fixされるかどうかはまた別と、理解は
しております。
目下の結論としては、この種の問題を避けるにはWindowsMediaを使うほか無い、です。
しかし、おっそいんですよねぇアレ。
以上、長文にお付き合いいただいてありがとうございました。
ちょうき
2004-08-26 06:30:50 ( ID:6rsdc3tzpv2 )
[ 削除 / 引用して返信 ]
これは簡単な実は話ですね。
MP2,3のディレイはエンコーダーによって違います。
LameとIISも違いますし、MP2でもしかりです。
ということはエンコーダーとデコーダーで1セットになっている必要があります。
しかし、どのエンコーダーでエンコードした物かはプログラムからは判りません。
また、デコーダーもしかりでTMPGEncで使われているデコーダーがどれかが不明ですし
バージョンによって変わる可能性もあります。(Sofdec、Cyberlink、MSの場合、まるもプラグイン等色々)
さらに、エンコード時に削ってしまうと、これまたデコーダが何で行われるか不明のため
多く削られる結果にもなりかねません。
TMPGEncに読みこみなおすだけの場合でもエンコーダーが何で行われたか不明のため・・・
これが延々続きます。
次に映像と音声ですが、TMPGEncシリーズは大抵長い方に合わせられます。
映像が長い場合は音声に不足分が足されます。
この時、映像エンコーダーなので映像の1フレーム単位で音声が補正されますね。
(映像1フレームで約33ms分ですね。)
ここで問題になるのが音声は1サンプル単位では存在できないという点です。
圧縮音声の場合は音声も圧縮がかかっているのである程度のブロックで1まとめにされています。
映像のGOP単位のような物です。
この1ブロックのサンプル数はmp2とかmp3とかac-3とかで違います。(1152サンプルとか1532とか)
こうなると数GOP内に完全一致する音声サンプルの存在はかなり難しい事がわかると思います。
*WindowsMediaも結局エンコーダ・デコーダを一致させることで解決していますね。
こだわり
2004-08-26 19:19:14 ( ID:1dmvss/ucbw )
[ 削除 / 引用して返信 ]
レスどうもです。
>さらに、エンコード時に削ってしまうと、これまたデコーダが何で行われるか不明のため
>多く削られる結果にもなりかねません。
ここは違うのでは? エンコーダで、デコーダの分も削れと言っているのではないのです。
エンコーダで発生する分はエンコーダで削ればよいのでは?と思うのですが…
原理上無理なんですかね。
デコーダで発生する分は、少なくともTMPGEncで読み込んで何かする場合には
何サンプル遅れるか判っているわけですから、伸張した後に補正する事が
できると思うのですが。内部処理が面倒になるのかもしれませんが、
それができれば再エンコで音がどんどんズレていくのも半分ほどになるかと。
その必要性をどう評価するかは微妙かもしれないですけど。
>ここで問題になるのが音声は1サンプル単位では存在できないという点です。
>圧縮音声の場合は音声も圧縮がかかっているのである程度のブロックで1まとめにされています。
>映像のGOP単位のような物です。
んん、これは考えてませんでした。やっかいですね。終端を1サンプル以内でぴったり
合わすのは無理なわけですね。ふーむ。エンコード時の遅延を削って出力できないのも
同じ理屈かな。遅延分が最初の圧縮単位に含まれてしまっているとなると
無理っぽいですね。
エンコードの遅延分については不承不承ですがガッテンしましょう。
それはそれとして、終端が何フレーム分もずれる事があるというのは、
何処かおかしいのではないかと思ってしまうわけですが。
ちょうき
2004-08-26 23:28:31 ( ID:6rsdc3tzpv2 )
[ 削除 / 引用して返信 ]
>エンコーダで発生する分はエンコーダで削ればよいのでは?
圧縮音声は時間軸の繋がりも持っています。
ですのでエンコード時に削ると先頭部に劣化が発生します。
これを防ぐにはエンコード字に伸びた分をデコード時に圧縮音声を展開後に補正するのが最も
高音質な処理と言えます。
つまりエンコード・デコードが1セットで扱えることが必須となってしまいます。
で、逆にエンコード時に削ってしまうと、デコーダーが万が一上記のようなデコード時に補正する様になっていたら
先頭が消し飛びます。
ちょっと朝にこだわりさんの説明文を見た時にはよく判らなかったのですが
残念ながら今見ても良く判りません(^^;
338549は0.3msでしょうか?
>エンコ後のものは途中から無音になっている場合が多い。
これは本来あるべき音が消失して無音になっているんでしょうか?
その場合、デコーダーのバグじゃないかな。モノラルmp2でMSデコーダならありえます。
それとも作ったmp2音声はまるもプラグインでTMPGEncに読み込んでいるんでしょうか?
あと、出力時の設定のフレームレートのところは29.97になっていますでしょうか?
最期にWAVファイルはWAVファイルリーダーのみで読み込んでいますでしょうか?
DirectShowなどであれば初期値でかなりズレが発生します。
ソース入力時はまるもプラグインかCRISofdec・WAVはWAVFileReaderで統一しておくといいと思います。
こだわり
2004-08-27 02:08:11 ( ID:1dmvss/ucbw )
[ 削除 / 引用して返信 ]
重ねてどうも。
>ちょっと朝にこだわりさんの説明文を見た時にはよく判らなかったのですが
>残念ながら今見ても良く判りません(^^;
>338549は0.3msでしょうか?
あらら、ごめんなさい、先頭の0が抜けてました。.は見えないですね。
0.338549 つまり338.5ミリ秒です。
>>エンコ後のものは途中から無音になっている場合が多い。
>これは本来あるべき音が消失して無音になっているんでしょうか?
どう解釈したものか…どちらかというと、無音部分のほうが余分と言うべきです。
無音になる部分で終わってくれていれば、余計なフレーム増加も少なくて済みます。
>それとも作ったmp2音声はまるもプラグインでTMPGEncに読み込んでいるんでしょうか?
mp2としては出力していません。「ファイルに出力」でPCMなWAVに出力しています。
DirectShowの優先度は初期値で…というか、テスト手順を読んでいただくと
…わかりにくい長ったらしい文章で済みませんです。
+481サンプル分を考慮するのを忘れていたし、データを手直しして再掲載しよう
かと思ったのですが、桁を揃えられなくて見難いのでやめておきます。
一度実際にやってみてもらえると助かるんですが…
29.97fpsで44.1kならソースは何でもいいです。44.1kにリサンプリングでも。
TMPGEncの標準状態で読み込み、先頭から5フレーム目(表示では4)を
終了フレームに指定、まず「ファイルに出力」で44.1k WAV作成、次にMPEG1を作成。
Audacityを入れるのが面倒ならWAVは要らないです。できたMPEGをTMPGEncで
読み込んでみてください。10フレーム増えているはずです。
また、音がガンガン鳴っているソースであれば6フレーム目の途中から
無音になっているのが判ると思います。
エンコ前にWAV出力した方は2フレーム分ほど長く、無音部分は無いです。
不思議じゃないですか? もし、それなりの理由があって10フレーム分も
音が長くなるのなら、面倒でも理屈を教えていただけると本当に助かりますです。
総フレーム数と標本化周波数の組み合わせによってどれだけ長くなるのか
計算できれば、フレーム数を変えて何度もエンコして実際に確かめる必要が
なくなりますので。
いや、最初からこう書けばよかったかな。(汗
ちょうき
2004-08-28 00:36:51 ( ID:6rsdc3tzpv2 )
[ 削除 / 引用して返信 ]
再現しない・・・
TMPGEnc Plus 2.5 2.521でやってますが再現しないですねぇ・・・
設定でWAVEリーダーとSofdec以外をOFFにして検証(tada.wavを使用)
tada.wavは22khzなのでリサンプルは高品質(低速)に設定し
tada.wavのみをMPEG-1でエンコード 音声TMPGEnc内蔵エンコーダーでmp2-44khz192khz Stereoに設定
出来上がったMPEG-1動画ファイルをTMPGEncに投下
ソースの範囲設定で0フレーム目から1フレーム目、3フレーム目、5フレーム目で範囲を区切って
ファイル出力からWAVファイル44khzで出力
これをAudacityと別のツールWaveSpectra for Windowsで検証
(AudacityとWaveSpectra for Windowsで計測されたsample数は一致しました。)
結果的にはこだわりさんの「A:期待されるサンプル数7357」と大差無い値が出ました
数値は「7356」でした。
うーん。もう一度ご確認されてはどうでしょうか?
こだわり
2004-08-28 17:51:03 ( ID:1dmvss/ucbw )
[ 削除 / 引用して返信 ]
>再現しない・・・
ええ〜っ!?
う〜ん、すみません、OSは何をお使いですか?
私はWin2kSp4+WMP9+WME+DirectX9.0c、映像・音声関係で
入れているのは DivX5.1Free,XviD,LAME.ACM,それからPowerDVDXP、
そのくらいです。もちろんAviUtlとかも入れてますが。
MS MPEG1 DecoderとWave File Reader以外切りましたし、
TMPGEncも違う場所に解凍して実行してみたりしましたが、
やっぱり、5フレームが15フレームになってしまいます。
頭抱えちゃいました。こういうおかしな悪さをするものって何でしょう?
ともあれ検証して頂いたおかげで新たな展開が…?
ちょうきさん有難うございます。
ちょうき
2004-08-28 20:29:24 ( ID:6rsdc3tzpv2 )
[ 削除 / 引用して返信 ]
昨日検証に使ったのはXP SP1のマシンとPlus2.521でした。
もう一機w2kマシンがあるのでこっちでもやってみました。
できれば環境に左右されない設定で行きましょう。
・TMPGEnc2.521Free版(私はPlusユーザーですがFree版をお使いのようですので)
・リサンプリングは高品質(低品質はWindows内蔵の為、環境により入れ替わるかもしれない)
・デコーダー(リーダー)はWAVEリーダー+まるもプラグイン0.6.48(http://www.marumo.ne.jp/mpeg2/)(MSMPEGデコーダーはWindows内蔵の為環境により変わるかもしれない)
・MP2エンコーダーは内蔵の物を使用する
・使用するWAVはXPにも2000にも入っているtada.wav
1、解凍したばかりの2521Free版で新規プロジェクトを開始する。上記条件を満たすように設定を変える。
2、tada.wavを2521に入力し、映像には何も付加せずにSystem(Video+Audio)で出力
(何もしなければこの設定のはず>MPEG-1 352x240 29.97fps CBR 1150kbps, Layer-2 44100Hz 192kbps)
3、出来上がったMPEG-1ファイルを2521に入力する
4、総フレーム数5枚分のWAVEファイルを取り出す為にソースの範囲で0〜4を指定する。
5、ファイルに出力>WAVE出力で44Khz16bitStereoになっている事を確認して出力
6、出力されたWAVEファイルのサンプル数を確認。
結果当方環境では7356サンプルでした。
このマシンはWindows2000SP4 WMP9(9.00.00.3075)
こだわり
2004-08-28 21:42:15 ( ID:1dmvss/ucbw )
[ 削除 / 引用して返信 ]
インストール時に削ったかして tada.wav が見当たらなかったので、
取り敢えずこれまでのを使いあとは同じ手順でやって…
おっと、違いを発見です。ずっとモノラルでやっていました!
で、ステレオソースであればWAV出力が長くなることはありませんでした。
しかしモノラルソースはやはり長くなっています。
モノ->ステレオ、その逆をやった場合も、ステレオは正常モノラルは異常
という結果になりました(Resample.dllのエラーが出る場合もありましたが)。
それから、音声ソースに別ファイルWAVを読み込んだ時と、
MP3使用のAVIファイルの場合には、モノラルであっても正常な長さでした。
しかし残念ながら、モノラルでもステレオでも、音声ソースが別であっても、
エンコ後には15フレームになってしまうのです。
モノラルの場合と、エンコード後の長さはどうでしょう?
お手数かけてすみませんです。
ちょうき
2004-08-28 22:22:53 ( ID:6rsdc3tzpv2 )
[ 削除 / 引用して返信 ]
ためして見ました
まるもプラグインはモノラルのmp2が読め無いようですね。
MSのMPEGデコーダーはモノラル音声の再生に色々なバグが有るので使わない方がいいです。
しかたがないので2.5.21のPlusを使用しました。
で、Freeではまるもを使っていた部分をCRISofdecに変更しました。
>2、tada.wavを2521に入力し、映像には何も付加せずにSystem(Video+Audio)で出力
この部分でステレオだったものをモノラルに変更
>5、ファイルに出力>WAVE出力で44Khz16bitStereoになっている事を確認して出力
ここでステレオとモノラルの両方を出力
出力されたサンプル数を確認
両方とも7356サンプルでした。
そう言えば、忘れてたけど2521の高品質はmono>Stereoに問題があったっけか・・・>最期にエラーが出る。
デコーダーに対して「ここからここまでのデータを下さい」と要求して「そのデータをこの形式で出力」
という命令をする時に
デコーダーが異常な数値を出してきた場合、勝手に削ったり、足したりする事はおそらく難しいと思います。
足す分は0で埋めるとかで回避できるかもしれませんが・・・
5フレーム分要求して15フレーム分のデータが来ても、それが5+10なのか
(1+1)+(1+1)+(1+1)・・・のデータなのかは不明です。
これを5+10であると断定できるならば10を削るだけで済みますが、デコーダーによって動作が違ったり
デコーダーが毎回違う値を返せば判別は無理です。
この辺りがデコーダーの精度とか信用度に関わってくると思います。
まるもプラグインやPlusのCRISofdecはその点、映像・音声ともに高精度だと思います。
WMPでMPEG-1のモノラルデータ音声付動画を再生する時に耳に聞こえて異常を発生させることもありますので
MSのMPEG-1デコーダーはあまり信用しない方が良いかと思います。
こだわり
2004-08-29 00:38:27 ( ID:1dmvss/ucbw )
[ 削除 / 引用して返信 ]
あの実は、sofdecって何?と思っていたのですが…
Plusに内蔵されているMPEGデコーダなんですね。
そこでPlus版を試用してみました。うん、何の不都合も無いです!
無料版でまるもプラグインのみで試したところやはり問題ない…
つまり、MSデコーダの問題という事ですね!
Plusでわざわざsofdecを内蔵しているのにはそれなりの訳があるわけですな。
さっきはステレオとモノラルの違いに気を取られてm2v.vfpで試すのを
忘れていたようです。音声対応は実験的なものでMPEG2Videoの読み込みが
主目的というのが頭にあり、補助的にしか使っていなかったので盲点でした。
簡単な結論にたどり着くのに随分回り道したようです。
こんなお馬鹿に付き合っていただいて本当に有難うございました。
こだわり
2004-08-29 03:12:24 ( ID:1dmvss/ucbw )
[ 削除 / 引用して返信 ]
追記です。せっかくなのでPlusで遊んでました。
Sofdecやm2p.vfpで希望どおりの長さの音声が出力されているかに見えたのですが、
5フレームの「はず」のファイルも、MPEGツールの分離でmp2を作りSofdecで
読み込んでみると、10フレームまでは行かないですが1フレーム分以上長い
データが存在しているようです。
長い映像ソースを読み込んでから、このmp2を読み込むと確認できます。
#Sofdecやm2p.vfpは映像の長さで音声を切り詰める仕様のようで。
先頭+481サンプル分だけ長いということも無いですし、
5フレームしかない映像ソースにそれ以上ある音声ソースを読み込んでも
5フレーム分しか出ないですし。
結局、この事によってMPEGツールでの結合や「UniteMovie」での結合では
音声が長くなってしまうようです。
PlusのMPEGツール結合の「編集」で長さを調べると、MSデコーダ使用なのか
5フレームのはずのファイルも15フレームありました。
うーむこれでは解決したようで解決していない。
エンコードされた時点で既に長いのはMPEG Audioの仕様なのですかね。
…もう、疲れましたね。(汗
|